From: cwc22@centipede.cl.cam.ac.uk Date: Fri, 11 Mar 2005 15:09:22 +0000 (+0000) Subject: bitkeeper revision 1.1236.26.1 (4231b4a20dnya9Kf1nGoYAKIhIcGJw) X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~17857^2~26^2~18^2 X-Git-Url: https://dgit.raspbian.org/%22http:/www.example.com/cgi/%22https:/%22bookmarks:/%22man:///%22http:/www.example.com/cgi/%22https:/%22bookmarks:/%22man:/?a=commitdiff_plain;h=29d187994b6ed6c834317fc0e64705b4c9bdf238;p=xen.git bitkeeper revision 1.1236.26.1 (4231b4a20dnya9Kf1nGoYAKIhIcGJw) Grant tables map operation working. --- diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index 3975190762..68d079e800 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -970,6 +970,10 @@ void domain_relinquish_memory(struct domain *d) /* Ensure that noone is running over the dead domain's page tables. */ synchronise_pagetables(~0UL); + /* Release device mappings of other domains */ + gnttab_release_dev_mappings( d->grant_table ); + + /* Exit shadow mode before deconstructing final guest page table. */ shadow_mode_disable(d); diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c index f228895bfc..c127c416f2 100644 --- a/xen/arch/x86/mm.c +++ b/xen/arch/x86/mm.c @@ -1976,13 +1976,6 @@ int update_grant_va_mapping(unsigned long va, * . check PTE being installed isn't DISALLOWED */ - /* Return value: - * -ve : error - * 0 : done - * GNTUPDVA_prev_ro : done & prior mapping was ro to same frame - * GNTUPDVA_prev_rw : done & prior mapping was rw to same frame - */ - int rc = 0; l1_pgentry_t *pl1e; unsigned long _ol1e; @@ -1998,18 +1991,7 @@ int update_grant_va_mapping(unsigned long va, l1_pgentry_t ol1e = mk_l1_pgentry(_ol1e); if ( update_l1e(pl1e, ol1e, mk_l1_pgentry(_nl1e)) ) - { - /* overwrote different mfn? */ - if (((_ol1e ^ _nl1e) & (PADDR_MASK & PAGE_MASK)) != 0) - put_page_from_l1e(ol1e, d); - - else if (_ol1e & _PAGE_PRESENT) - rc = ((_ol1e & _PAGE_RW) ? GNTUPDVA_prev_rw - : GNTUPDVA_prev_ro ); - /* use return code to avoid nasty grant table - * slow path in put_page_from_l1e -- caller - * must handle grant ref count instead. */ - } + put_page_from_l1e(ol1e, d); else rc = -EINVAL; } diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c index b8302b6483..e5c5f92763 100644 --- a/xen/common/grant_table.c +++ b/xen/common/grant_table.c @@ -227,6 +227,8 @@ __gnttab_map_grant_ref( if ( (act->pin & 0x80808080U) != 0 ) PIN_FAIL(ENOSPC, "Risk of counter overflow %08x\n", act->pin); + frame = act->frame; + if ( !(flags & GNTMAP_readonly) && !((sflags = sha->flags) & GTF_writing) ) { @@ -256,8 +258,6 @@ __gnttab_map_grant_ref( sflags = prev_sflags; } - frame = act->frame; - if ( unlikely(!get_page_type(&frame_table[frame], PGT_writable_page)) ) { @@ -275,14 +275,9 @@ __gnttab_map_grant_ref( GNTPIN_hstr_inc : GNTPIN_hstw_inc; } - ld->grant_table->maptrack[handle].domid = dom; - ld->grant_table->maptrack[handle].ref_and_flags = - (ref << MAPTRACK_REF_SHIFT) | (flags & MAPTRACK_GNTMAP_MASK); - /* At this point: * act->pin updated to reflect mapping * sha->flags updated to indicate to granting domain mapping done - * maptrack points to correct remote domain data * frame contains the mfn */ @@ -290,12 +285,22 @@ __gnttab_map_grant_ref( { /* Write update into the pagetable */ - if ( 0 > (rc = update_grant_va_mapping( host_virt_addr, + + /* cwc22: TODO: check locking... */ + + spin_unlock(&rd->grant_table->lock); + + rc = update_grant_va_mapping( host_virt_addr, (frame << PAGE_SHIFT) | _PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_DIRTY | ((flags & GNTMAP_readonly) ? 0 : _PAGE_RW), - ld, led )) ) + ld, led ); + DPRINTK("update_grant_va_mapping : rc %d\n", rc); + + spin_lock(&rd->grant_table->lock); + + if ( 0 > rc ) { /* Abort. */ act->pin -= (flags & GNTMAP_readonly) ? @@ -306,37 +311,20 @@ __gnttab_map_grant_ref( else { act->pin -= GNTPIN_hstw_inc; - if ( (act->pin & (GNTPIN_hstw_mask | GNTPIN_hstr_mask)) == 0 ) + if ( (act->pin & (GNTPIN_hstw_mask|GNTPIN_devw_mask)) == 0 ) { put_page_type(&frame_table[frame]); clear_bit(_GTF_writing, &sha->flags); } - - if ( act->pin == 0 ) - { - put_page(&frame_table[frame]); - clear_bit(_GTF_reading, &sha->flags); - } } - goto fail; - } - - /* Check to see if update overwrote a mapping of the same mfn - * - if so, must handle ref count here - */ - if ( rc == GNTUPDVA_prev_ro ) - act->pin -= GNTPIN_hstr_inc; - - if ( rc == GNTUPDVA_prev_rw ) - { - act->pin -= GNTPIN_hstw_inc; - - if ( (act->pin & (GNTPIN_hstw_mask | GNTPIN_devw_mask)) == 0 ) + if ( act->pin == 0 ) { - put_page_type(&frame_table[frame]); - clear_bit(_GTF_writing, &sha->flags); + put_page(&frame_table[frame]); + clear_bit(_GTF_reading, &sha->flags); } + goto fail; } + rc = 0; *va = host_virt_addr; @@ -345,6 +333,12 @@ __gnttab_map_grant_ref( */ } + /* Only make the maptrack live _after_ writing the pte, in case + * we overwrite the same frame number, causing a maptrack walk to find it */ + ld->grant_table->maptrack[handle].domid = dom; + ld->grant_table->maptrack[handle].ref_and_flags = + (ref << MAPTRACK_REF_SHIFT) | (flags & MAPTRACK_GNTMAP_MASK); + /* Unchecked and unconditional writes to user uop. */ if ( flags & GNTMAP_device_map ) (void)__put_user(frame, &uop->dev_bus_addr); @@ -437,6 +431,8 @@ __gnttab_unmap_grant_ref( act = &rd->grant_table->active[ref]; sha = &rd->grant_table->shared[ref]; + // cwc22: TODO: put_maptrack_handle + spin_lock(&rd->grant_table->lock); if ( frame != 0 ) @@ -643,9 +639,9 @@ gnttab_dump_table(gnttab_dump_table_t *uop) if ( act->pin || act->domid || act->frame || sha_copy.flags || sha_copy.domid || sha_copy.frame ) { - DPRINTK("Grant: dom (%hu) ACTIVE (%d) pin:(%x) dom:(%hu) frame:(%u)\n", + DPRINTK("Grant: dom (%hu) ACTIVE (%d) pin:(%x) dom:(%hu) frame:(%lx)\n", op.dom, i, act->pin, act->domid, act->frame); - DPRINTK("Grant: dom (%hu) SHARED (%d) flags:(%hx) dom:(%hu) frame:(%u)\n", + DPRINTK("Grant: dom (%hu) SHARED (%d) flags:(%hx) dom:(%hu) frame:(%lx)\n", op.dom, i, sha_copy.flags, sha_copy.domid, sha_copy.frame); } @@ -729,6 +725,11 @@ gnttab_check_unmap( * also traverse this. */ + /* Note: if the same frame is mapped multiple times, and then one of + * the ptes is overwritten, which maptrack handle gets invalidated? + * Advice: don't do it. + */ + unsigned int handle, ref, refcount; grant_table_t *lgt, *rgt; active_grant_entry_t *act; @@ -741,8 +742,6 @@ gnttab_check_unmap( if ( lgt->map_count == 0 ) return 0; - rgt = rd->grant_table; - #ifdef GRANT_DEBUG if ( ld->id != 0 ) { DPRINTK("Foreign unref rd(%d) ld(%d) frm(%x) flgs(%x).\n", @@ -750,6 +749,14 @@ gnttab_check_unmap( } #endif + if ( get_domain(rd) == 0 ) + { + DPRINTK("gnttab_check_unmap: couldn't get_domain rd(%d)\n", rd->id); + return 0; + } + + rgt = rd->grant_table; + for ( handle = 0; handle < NR_MAPTRACK_ENTRIES; handle++ ) { map = &lgt->maptrack[handle]; @@ -792,7 +799,7 @@ gnttab_check_unmap( act->pin -= GNTPIN_hstw_inc; /* any more granted writable mappings? */ - if ( (act->pin & (GNTPIN_hstw_mask | GNTPIN_hstr_mask)) == 0 ) + if ( (act->pin & (GNTPIN_hstw_mask|GNTPIN_devw_mask)) == 0 ) { put_page_type(&frame_table[frame]); clear_bit(_GTF_writing, &rgt->shared[ref].flags); @@ -815,6 +822,7 @@ gnttab_check_unmap( break; } } + put_domain(rd); return found; } @@ -956,6 +964,79 @@ grant_table_create( return -ENOMEM; } +void +gnttab_release_dev_mappings(grant_table_t *gt) +{ + grant_mapping_t *map; + domid_t dom; + grant_ref_t ref; + u16 handle; + struct domain *ld, *rd; + unsigned long frame; + active_grant_entry_t *act; + grant_entry_t *sha; + + ld = current->domain; + + for ( handle = 0; handle < NR_MAPTRACK_ENTRIES; handle++ ) + { + map = >->maptrack[handle]; + + if ( map->ref_and_flags & GNTMAP_device_map ) + { + dom = map->domid; + ref = map->ref_and_flags >> MAPTRACK_REF_SHIFT; + + DPRINTK("Grant release (%hu) ref:(%hu) flags:(%x) dom:(%hu)\n", + handle, ref, + map->ref_and_flags & MAPTRACK_GNTMAP_MASK, dom); + + if ( unlikely((rd = find_domain_by_id(dom)) == NULL) || + unlikely(ld == rd) ) + { + if ( rd != NULL ) + put_domain(rd); + + printk(KERN_WARNING "Grant release: Could not find domain %d\n", dom); + continue; + } + + act = &rd->grant_table->active[ref]; + sha = &rd->grant_table->shared[ref]; + + spin_lock(&rd->grant_table->lock); + + if ( act->pin & (GNTPIN_devw_mask | GNTPIN_devr_mask) ) + { + frame = act->frame; + + if ( ( (act->pin & GNTPIN_hstw_mask) == 0 ) && + ( (act->pin & GNTPIN_devw_mask) > 0 ) ) + { + clear_bit(_GTF_writing, &sha->flags); + put_page_type(&frame_table[frame]); + } + + act->pin &= ~(GNTPIN_devw_mask | GNTPIN_devr_mask); + + if ( act->pin == 0 ) + { + clear_bit(_GTF_reading, &sha->flags); + map->ref_and_flags = 0; + put_page(&frame_table[frame]); + } + else + map->ref_and_flags &= ~GNTMAP_device_map; + } + + spin_unlock(&rd->grant_table->lock); + + put_domain(rd); + } + } +} + + void grant_table_destroy( struct domain *d) diff --git a/xen/include/asm-x86/mm.h b/xen/include/asm-x86/mm.h index e6bd40560d..99cfee4e22 100644 --- a/xen/include/asm-x86/mm.h +++ b/xen/include/asm-x86/mm.h @@ -343,7 +343,4 @@ int update_grant_va_mapping(unsigned long va, unsigned long val, struct domain *d, struct exec_domain *ed); -#define GNTUPDVA_prev_ro 1 -#define GNTUPDVA_prev_rw 2 - #endif /* __ASM_X86_MM_H__ */ diff --git a/xen/include/xen/grant_table.h b/xen/include/xen/grant_table.h index 9520fbca45..b05ca702ce 100644 --- a/xen/include/xen/grant_table.h +++ b/xen/include/xen/grant_table.h @@ -106,4 +106,8 @@ void gnttab_notify_transfer( struct domain *rd, grant_ref_t ref, unsigned long frame); +/* Pre-domain destruction release of granted device mappings of other domains.*/ +void +gnttab_release_dev_mappings(grant_table_t *gt); + #endif /* __XEN_GRANT_H__ */